package com.gitee.ed.common;

import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;

import java.util.*;
import java.util.function.Function;

/**
 * 通用工具类
 *
 * @author hongda.li
 */
public final class CommonUtils {
    private CommonUtils() {
    }

    /**
     * 获取类的优先级
     * 基于优先级注解 {@link com.gitee.ed.common.Priority}
     *
     * @param clazz 任意非空类
     * @return 优先级
     */
    public static int parsePriority(Class<?> clazz) {
        Objects.requireNonNull(clazz);
        Priority priority = AnnotationUtil.getAnnotation(clazz, Priority.class);
        if (priority == null) {
            return Priority.NORMAL_PRIORITY;
        } else {
            return priority.value();
        }
    }

    /**
     * 将数组转为 Map 结果
     * JDK 提供的 Stream 方式转 Map 无法存储 Null 元素
     *
     * @param keyMapping   唯一键生成器
     * @param valueMapping 键值对生成器
     * @param elements     元素数组
     * @param <K>          键泛型
     * @param <V>          值泛型
     * @param <E>          元素泛型
     * @return 最终的 Map 结果
     */
    public static <K, V, E> Map<K, V> toLinkedHashMap(Function<E, K> keyMapping,
                                                      Function<E, V> valueMapping,
                                                      E[] elements) {
        return CommonUtils.toLinkedHashMap(keyMapping, valueMapping, Arrays.asList(elements));
    }

    /**
     * 将集合转为 Map 结果
     * JDK 提供的 Stream 方式转 Map 无法存储 Null 元素
     *
     * @param keyMapping   唯一键生成器
     * @param valueMapping 键值对生成器
     * @param elements     元素集合
     * @param <K>          键泛型
     * @param <V>          值泛型
     * @param <E>          元素泛型
     * @return 最终的 Map 结果
     */
    public static <K, V, E> Map<K, V> toLinkedHashMap(Function<E, K> keyMapping,
                                                      Function<E, V> valueMapping,
                                                      Collection<E> elements) {
        if (CollUtil.isEmpty(elements)) {
            return LinkedHashMap.newLinkedHashMap(2);
        } else {
            Map<K, V> result = LinkedHashMap.newLinkedHashMap(elements.size());
            elements.forEach(element -> result.put(keyMapping.apply(element), valueMapping.apply(element)));
            return result;
        }
    }
}
